Importing Libraries¶
In [118]:
import pandas as pd
from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut, GeocoderUnavailable
from shapely.geometry import Point
import geopandas as gpd
import time
import requests
import osmnx as ox
import folium
Collecting Bus Stop Information¶
In [478]:
### Getting bus data
place = "Baku, Azerbaijan"
tags = {"highway": "bus_stop"}
gdf_bus = ox.features_from_place(place, tags)
In [480]:
gdf_bus = gdf_bus.to_crs("EPSG:32638")
In [499]:
gdf_bus.head()
Out[499]:
| geometry | bus | highway | name | public_transport | bench | bin | lit | shelter | addr:street | ... | covered | name:signed | description | note | outdoor_seating | passenger_information_display | source_ref | source_ref:url | addr:housenumber | ref | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| element | id | |||||||||||||||||||||
| node | 852866220 | POINT (910555.168 4485348.981) | yes | bus_stop | Corce Enesku parkı | platform | yes | NaN | NaN | yes | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1001147686 | POINT (937799.515 4494655.431) | NaN | bus_stop | Mərdəkan \ Avtovağzal | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
| 1213299578 | POINT (908812.351 4485463.556) | yes | bus_stop | Göz klinikası 1 | platform | yes | no | no | yes | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
| 1213299601 | POINT (908461.651 4485617.557) | yes | bus_stop | Mir Cəlal küçəsi elektrik yarımstansiyası | platform | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
| 1213339341 | POINT (908511.995 4484994.026) | yes | bus_stop | 111 nömrəli tam orta məktəb | platform | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
5 rows × 37 columns
In [187]:
gdf_bus.explore()
Out[187]:
Make this Notebook Trusted to load map: File -> Trust Notebook
Collecting University Information¶
In [400]:
tags = {"amenity": ["university", "college"]}
gdf_universities = ox.features_from_place(place, tags)
# in order to not to miss university campuses we will convert polygons to centroids
points = gdf_universities[gdf_universities.geometry.geom_type == 'Point']
polygons = gdf_universities[gdf_universities.geometry.geom_type.isin(['Polygon', 'MultiPolygon'])]
polygons = polygons.to_crs(epsg=32638)
points = points.to_crs(epsg = 32638)
polygons['geometry'] = polygons.geometry.centroid
In [402]:
# combining all points
universities_all = pd.concat([points, polygons])
In [497]:
universities_all.head()
Out[497]:
| geometry | addr:city | addr:country | addr:housenumber | addr:street | amenity | name | name:az | name:en | name:ru | ... | height | internet_access | internet_access:fee | description | type | contact:phone | contact:website | name:ja | bus_stop_distance | name_lower | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| element | id | |||||||||||||||||||||
| node | 2037930732 | POINT (912189 4483597.514) | Bakı | NaN | NaN | Fətəli Xan Xoyski prospekti | university | Azərbaycan Dövlət Bədən Tərbiyəsi və İdman Aka... | Dövlət Bədən Tərbiyəsi və İdman Akademiyası | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 177.644893 | azərbaycan dövlət bədən tərbiyəsi və i̇dman ak... |
| 2066367012 | POINT (910233.594 4479498.916) | Bakı | AZ | 31 | İstiqlaliyyət | university | Qərbi Kaspi Universiteti | Qərbi Kaspi Universiteti | Western Caspian University | Западно-Каспийский университет | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 28.442976 | qərbi kaspi universiteti | |
| 2135629462 | POINT (909615.846 4481616.159) | Bakı | NaN | NaN | Bəsti Bağırova küç. | college | 1 saylı Bakı Tibb Kolleci | 1 saylı Bakı Tibb Kolleci | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 96.218798 | 1 saylı bakı tibb kolleci | |
| 2485919776 | POINT (910550.53 4484500.647) | NaN | NaN | NaN | NaN | university | Azərbaycan Kooperasiya Universiteti | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 146.316574 | azərbaycan kooperasiya universiteti | |
| 2485919777 | POINT (910599.497 4484533.912) | NaN | NaN | NaN | NaN | college | Bakı Biznes və Kooperasiya Kolleci | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 170.865342 | bakı biznes və kooperasiya kolleci |
5 rows × 56 columns
In [404]:
universities_all.shape
Out[404]:
(198, 54)
In [574]:
universities_all.explore(color='blue',
marker_kwds={ 'radius': 2,},
tooltip='name')
Out[574]:
Make this Notebook Trusted to load map: File -> Trust Notebook
Universities More Than 500 m from Bus Stops¶
In [424]:
# calculating minimum distance for universities from bus stops
universities_all['bus_stop_distance'] = universities_all.geometry.apply(
lambda univ: univ.distance(gdf_bus.geometry).min())
In [454]:
universities_all['name_lower'] = universities_all['name'].str.lower()
In [482]:
# finding universities that fall more than 500 m from bus stops
far_universities = universities_all[universities_all['bus_stop_distance']>500]
far_universities= far_universities[['geometry','name_lower','name','bus_stop_distance']]
In [484]:
keywords = ['lisey', 'universitet', 'kollec', 'ali məktəb']
pattern = '|'.join(keywords)
filtered_df = far_universities[far_universities['name_lower'].str.contains(pattern, case=False, na=False)]
filtered_df[['name','bus_stop_distance']].sort_values(by = 'bus_stop_distance',ascending = False).reset_index(drop = True)
Out[484]:
| name | bus_stop_distance | |
|---|---|---|
| 0 | 8 saylı Bakı Peşə Liseyi | 6884.756811 |
| 1 | 8 saylı Peşə Liseyi \ Qızıldaş | 6853.965995 |
| 2 | Moskva Dövlət Universitetinin Bakı Filialı | 2486.837826 |
| 3 | Yanğın Texniki Kolleci \ Hövsan | 1488.165270 |
| 4 | 101 saylı Peşə Liseyi \ Binə | 1280.422284 |
| 5 | 5 saylı Bakı Peşə Liseyi | 679.200448 |
| 6 | 12 saylı Bakı Peşə Liseyi \ Bakıxanov | 620.627620 |
| 7 | Celt Kollec \ Bakıxanov | 581.536615 |
| 8 | 1 saylı Bakı Peşə Liseyi \ Bakıxanov | 544.571625 |
| 9 | Xəzər Universiteti | 535.178587 |
In [548]:
filtered_df = filtered_df.to_crs(epsg=4326)
# centering map roughly on Baku
m = folium.Map(location=[40.4093, 49.8671], zoom_start=12)
for idx, row in filtered_df.iterrows():
lon, lat = row.geometry.x, row.geometry.y
folium.Marker(
location=[lat, lon],
popup=row['name'],
icon=folium.Icon(icon='flag', color='red'),
tooltip=row['name'],
).add_to(m)
m.save("university_distance.html")
m
Out[548]:
Make this Notebook Trusted to load map: File -> Trust Notebook
We identified educational Institutions that are located more than 500 meters from the nearest bus stops. This highlights areas where public transportation could be more convenient for students¶
Collecting Bike Lane Information¶
In [6]:
place = "Baku, Azerbaijan"
tags = {"highway": "cycleway"}
gdf_bike_path = ox.features_from_place(place, tags)
In [8]:
gdf_bike_path = gdf_bike_path.to_crs(epsg=3857)
gdf_bike_path['length_m'] = gdf_bike_path.geometry.length
In [10]:
# getting index of max length bike line
max_bike_length = gdf_bike_path['length_m'].sort_values(ascending=False).idxmax()
max_bike_length
Out[10]:
('way', 1259359139)
In [506]:
gdf_bike_path.loc[max_bike_length].explore(style_kwds={'weight': 3, 'opacity': 1,'color':'blue'})
Out[506]:
Make this Notebook Trusted to load map: File -> Trust Notebook
Longest bike lane is in Mardəkan-Buzovna¶
Loading regions dataset¶
Data source: https://opendata.az/
In [22]:
gdf_regions = gpd.read_file('azrbaycan_rayonlar.geojson')
gdf_regions.head(2)
Out[22]:
| OBJECTID | Name_AZ | Name | PARENT_ID | Code_OSM | Name_RU | Area | Shape_Leng | Shape_Le_1 | ID | Shape_Le_2 | Shape_Length | Shape_Area | Upper_case | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | Qax | Gakh | 1 | 1204 | Гах | 1487.563667 | 3.145374 | 3.145374 | 403.0 | 3.145374 | 3.145374 | 0.159953 | QAX | POLYGON ((47.01821 41.5551, 47.01816 41.55467,... |
| 1 | 2 | Zaqatala | Zagatala | 1 | 1204 | Закатала | 1354.885693 | 2.853307 | 2.853307 | 402.0 | 2.853307 | 2.853307 | 0.146303 | ZAQATALA | MULTIPOLYGON (((46.47881 41.64208, 46.47853 41... |
In [23]:
gdf_baku_regions = gdf_regions.loc[gdf_regions.Name_AZ.isin(['Nərimanov', 'Nizami', 'Pirallahı','Qaradağ', 'Sabunçu', 'Səbail', 'Suraxanı', 'Xətai', 'Xəzər',
'Yasamal', 'Binəqədi', 'Nəsimi']),['Name','geometry']].reset_index(drop = True)
In [583]:
gdf_baku_regions.explore(column = 'Name',tooltip = 'Name', style_kwds = {'fillOpacity': 0.7,'color':'gray'})
Out[583]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [28]:
gdf_baku_regions['Area'] = gdf_baku_regions.to_crs(epsg = 32638).geometry.area
In [34]:
gdf_baku_regions[['Name','Area']].sort_values(by = 'Area', ascending = False).reset_index(drop = True)
Out[34]:
| Name | Area | |
|---|---|---|
| 0 | Garadagh | 1.067115e+09 |
| 1 | Khazar | 3.403013e+08 |
| 2 | Sabunchu | 2.086572e+08 |
| 3 | Surakhani | 1.304281e+08 |
| 4 | Binagadi | 9.365016e+07 |
| 5 | Pirallahi | 7.991648e+07 |
| 6 | Khatai | 3.479748e+07 |
| 7 | Sabail | 2.950769e+07 |
| 8 | Narimanov | 2.054510e+07 |
| 9 | Nizami | 1.995318e+07 |
| 10 | Yasamal | 1.636858e+07 |
| 11 | Nasimi | 9.924848e+06 |
We see that largest district is Garadagh and smallest one is Nasimi
Total bike lane length per district in kilometers¶
In [546]:
m = gdf_baku_regions.explore(column = 'Name',color="darkblue", style_kwds={'fillOpacity': 0.5, 'color': 'gray'},)
gdf_bike_path.explore(m=m, color="darkblue",style_kwds={"weight": 3})
m.save("bike_district.html")
m
Out[546]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [46]:
districts = gdf_baku_regions.to_crs(epsg = 3857)
bike_lengths = gpd.overlay(bike_paths,districts,how = 'intersection')
In [48]:
bike_lengths.columns
Out[48]:
Index(['highway', 'crossing', 'bicycle', 'foot', 'surface', 'incline',
'maxspeed', 'crossing:markings', 'cycleway', 'lit', 'embankment',
'oneway', 'crossing:island', 'length_m', 'Name', 'Area', 'geometry'],
dtype='object')
In [54]:
result = bike_lengths.groupby('Name')['length_m'].sum().reset_index()
result['length_km'] = result['length_m']/1000
result.sort_values(by = 'length_km',ascending = False).reset_index(drop = True)
Out[54]:
| Name | length_m | length_km | |
|---|---|---|---|
| 0 | Sabail | 12690.061022 | 12.690061 |
| 1 | Khazar | 10114.345614 | 10.114346 |
| 2 | Khatai | 8308.105543 | 8.308106 |
| 3 | Nasimi | 2406.764391 | 2.406764 |
| 4 | Yasamal | 1769.567334 | 1.769567 |

